/*
 * Copyright (c) 2010, Michael Hengler (developer (at) hengler (dot) de),
 * Nikolaus Moll (developer (at) miblounge (dot) net).
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * * Neither the name of the Jombi project nor the
 * names of its contributors may be used to endorse or promote products
 * derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL JOMBI BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */
package net.miblounge.jombi.impl.widgets;

import net.miblounge.jombi.impl.image.QtImageRegistry;
import net.miblounge.jombi.impl.layout.LayoutManagerImpl;
import net.miblounge.miglayout.qt.MigLayout;

import org.jowidgets.common.widgets.IButtonCommon;
import org.jowidgets.common.widgets.IWidgetCommon;
import org.jowidgets.common.widgets.factory.IGenericWidgetFactory;
import org.jowidgets.common.widgets.layout.ILayoutDescriptor;
import org.jowidgets.common.widgets.layout.ILayouter;
import org.jowidgets.common.widgets.layout.MigLayoutDescriptor;
import org.jowidgets.spi.widgets.IFrameSpi;
import org.jowidgets.spi.widgets.IMenuBarSpi;
import org.jowidgets.spi.widgets.setup.IFrameSetupSpi;
import org.jowidgets.util.Assert;

import com.trolltech.qt.core.QEvent;
import com.trolltech.qt.core.QEvent.Type;
import com.trolltech.qt.core.QObject;
import com.trolltech.qt.core.QSize;
import com.trolltech.qt.core.Qt.DockWidgetArea;
import com.trolltech.qt.core.Qt.WidgetAttribute;
import com.trolltech.qt.gui.QDockWidget;
import com.trolltech.qt.gui.QMainWindow;
import com.trolltech.qt.gui.QToolBar;
import com.trolltech.qt.gui.QWidget;

public class FrameImpl extends QtWindow implements IFrameSpi {
	private final QWidget clientArea;

	public FrameImpl(final IGenericWidgetFactory factory, final QtImageRegistry imageRegistry, final IFrameSetupSpi setup) {
		super(factory, new QMainWindow());
		getUiReference().setDockNestingEnabled(true);

		getUiReference().installEventFilter(new QObject() {
			@Override
			public boolean eventFilter(final QObject sender, final QEvent e) {
				if (e.type() == Type.Close) {
					getUiReference().close();
				}
				return super.eventFilter(sender, e);
			}
		});

		getUiReference().setWindowTitle(setup.getTitle());
		clientArea = new QWidget(getUiReference()) {
			@Override
			public String toString() {
				return "QWidget [MainWindow Central Widget]";
			}
		};
		clientArea.setVisible(true);
		getUiReference().setCentralWidget(clientArea);

		setIcon(setup.getIcon(), imageRegistry);
	}

	@Override
	public QMainWindow getUiReference() {
		return (QMainWindow) super.getUiReference();
	}

	@Override
	public void setLayout(final ILayoutDescriptor layoutManager) {
		Assert.paramNotNull(layoutManager, "layoutManager");

		// delete old layout if necessary
		if (clientArea.layout() != null) {
			clientArea.layout().dispose();
		}

		if (layoutManager instanceof MigLayoutDescriptor) {
			final MigLayoutDescriptor migLayoutManager = (MigLayoutDescriptor) layoutManager;
			clientArea.setLayout(new MigLayout(
				migLayoutManager.getLayoutConstraints(),
				migLayoutManager.getColumnConstraints(),
				migLayoutManager.getRowConstraints()));
		} else if (layoutManager instanceof ILayouter) {
			clientArea.setLayout(new LayoutManagerImpl(getUiReference(), (ILayouter) layoutManager));
		} else {
			throw new IllegalArgumentException("Layout Manager of type '"
				+ layoutManager.getClass().getName()
				+ "' is not supported");
		}
	}

	@Override
	protected void addToContainer(final Integer index, final IWidgetCommon widget, final Object cellConstraints) {
		// TODO NM index
		if (clientArea.layout() instanceof MigLayout) {
			final MigLayout layout = (MigLayout) clientArea.layout();

			// this workaround is necessary to keep the toolbar on top
			if (widget.getUiReference() instanceof QToolBar) {
				final QToolBar toolbar = (QToolBar) widget.getUiReference();
				toolbar.setMovable(false);
				getUiReference().addToolBar(toolbar);

				// fix layout
				final QWidget emptyWidget = new QWidget() {
					@Override
					public QSize sizeHint() {
						return new QSize(0, 0);
					}
				};
				if (cellConstraints != null) {
					layout.addWidget(emptyWidget, cellConstraints);
				} else {
					layout.addWidget(emptyWidget);
				}
				return;
			}

			if (widget.getUiReference() instanceof QDockWidget) {
				final QDockWidget dockWidget = (QDockWidget) widget.getUiReference();
				getUiReference().addDockWidget(DockWidgetArea.LeftDockWidgetArea, dockWidget);

				// fix layout
				final QWidget emptyWidget = new QWidget() {
					@Override
					public QSize sizeHint() {
						return new QSize(0, 0);
					}
				};
				if (cellConstraints != null) {
					layout.addWidget(emptyWidget, cellConstraints);
				} else {
					layout.addWidget(emptyWidget);
				}
				return;
			}

			if (!(widget.getUiReference() instanceof QWidget)) {
				// fix layout
				final QWidget emptyWidget = new QWidget() {
					@Override
					public QSize sizeHint() {
						return new QSize(0, 0);
					}
				};
				if (cellConstraints != null) {
					layout.addWidget(emptyWidget, cellConstraints);
				} else {
					layout.addWidget(emptyWidget);
				}
				return;
			}

			if (cellConstraints != null) {
				layout.addWidget((QWidget) widget.getUiReference(), cellConstraints);
			} else {
				layout.addWidget((QWidget) widget.getUiReference());
			}
		} else if (clientArea.layout() instanceof LayoutManagerImpl) {
			final LayoutManagerImpl layoutManager = (LayoutManagerImpl) clientArea.layout();
			layoutManager.addLayoutComponent((QWidget) widget.getUiReference(), cellConstraints);
		} else {
			throw new IllegalArgumentException("Layout Manager of type '"
				+ clientArea.layout().getClass().getName()
				+ "' is not supported");
		}

	}

	@Override
	public void removeAll() {
		// TODO: remove dockable windows as well?
		if (!(clientArea.layout() instanceof MigLayout)) {
			throw new IllegalArgumentException("Layout Manager of type '"
				+ clientArea.layout().getClass().getName()
				+ "' is not supported");
		}

		final MigLayout layout = (MigLayout) clientArea.layout();
		// remove from layout
		while (layout.count() > 0) {
			layout.takeAt(0);
		}

		// remove children
		for (final QObject child : clientArea.children()) {
			if (child.isWidgetType()) {
				final QWidget widget = (QWidget) child;
				widget.setParent(null);
				widget.setAttribute(WidgetAttribute.WA_DeleteOnClose);
				widget.close();
			}
		}
	}

	@Override
	public IMenuBarSpi createMenuBar() {
		return new MenuBarImpl(getUiReference().menuBar());
	}

	@Override
	public void setDefaultButton(final IButtonCommon button) {
		// not supportet in qt
	}

}
